

// ## 自写一个 VueRouter 模块，路由文件中import模块
// ## 实现去除 import VueRouter from 'vue-router'

let _Vue = null  // 初始化 第二件事

export default class VueRouter {
  static install(Vue) {
    //1 判断当前插件是否被安装
    // 安装了则不需要做任何事，没有安装则设置 installed 属性为 true
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true

    //2 把Vue的构造函数记录在全局
    _Vue = Vue

    //3 把创建Vue的实例传入的router对象注入到Vue实例
    // _Vue.prototype.$router = this.$options.router
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          // this.$options.router.init()   hash 模式添加
        }

      }
    })
  }

  // Vue Router 构造函数 Constructor(Options) : VueRouter
  // Options选项 返回vue对象
  // 这个构造函数中，需要初始化三个属性: 
  // options : 承载传入的 options
  // data：需设置为响应式data，因为：会存储路由地址，路由变化，加载不同组件) 
  // routeMap ：路由规则，根据变化，渲染不同组件
  // Vue.observable()  创建响应式对象
  constructor(options) {
    this.options = options
    this.routeMap = {} // 路由规则
    // observable
    this.data = _Vue.observable({
      current: '/'  // 当前路由地址， 默认 /
    })
    // this.init()
  }

  init() {
    this.createRouteMap()
    this.initComponent(_Vue)
    this.initEvent()
  }

  createRouteMap() {
    //遍历所有的路由规则 把路由规则解析成键值对的形式存储到routeMap中
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    });
  }

  // 实现 initComponents 方法，
  // Vue构造函数，传入这个参数 是为了减少对外部的依赖
  // 方法内创建  router-link 组件,用 vue.component(), 最终渲染成超链接,to 接收一个地址
  // props  接收一个传入的 to，定义为字符串, template 渲染成超链接
  // <slot></slot>   挖坑 插槽，放将来输入的内容
  // 创建  router-view 组件
  initComponent(Vue) {
    // 先创建第一个组件  router-link
    Vue.component("router-link", {
      props: {
        to: String
      },
      render(h) {
        return h("a", {
          attrs: {
            href: this.to
            // href: '#' + this.to   // hash 模式
          },
          on: {
            click: this.clickhander
          }
        }, [this.$slots.default])
      },
      methods: {
        clickhander(e) {
          // 改变URL地址栏，但不发送请求，并记录历史，有三个参数( data, title, 地址 )
          history.pushState({}, '', this.to) // this.to：超链接要跳转的地址
          // 加载路径组件，当前路径记录到 this.data.current 里
          this.$router.data.current = this.to
          e.preventDefault()
        }
        // hash 模式：
        // clickHandler(e) {
        //   window.location.hash = '#' + this.to
        //   this.$router.data.current = this.to
        //   e.preventDefault()
        // }
      }
      // template:"<a :href='to'><slot></slot><>"
    }) // router-link 组件创造 结束

    // 创建第二个组件  router-view, 相当于一个页面的占位符
    const self = this
    Vue.component("router-view", {
      render(h) {
        // 先找到当前路由的地址  this.data.current ，去routeMap中找组件
        // self.data.current
        const component = self.routeMap[self.data.current]
        return h(component)
      }
    })

  }
  initEvent() {
    // 注册 popState 事件, 注册后，放init方法里调用
    window.addEventListener("popstate", () => { // 箭头函数不改变this指向
      this.data.current = window.location.pathname
    })
    /**
     * hash 模式
      window.addEventListener('load', this.hashChange.bind(this))
      window.addEventListener('hashchange', this.hashChange.bind(this))
     * 
     */
  }
  /**
   * 
    hashChange() {
      if (!window.location.hash) {
          window.location.hash = '#/'
      }
      this.data.current = window.location.hash.substr(1)
    }
   */
}